package gz.metro.datasync.utils;


import gz.metro.datasync.utils.enums.SqlRules;
import gz.metro.datasync.utils.page.PageQueryRequest;
import gz.metro.datasync.utils.page.PagerVO;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author ：张任豪
 * @date ：2022/10/9 9:39
 * @description：
 */
@Slf4j
@Component
public class JdbcHelper extends JdbcTemplate {

    public JdbcHelper(DataSource dataSource) {
        this.setDataSource(dataSource);
    }


    public void execute(String sql, Map<String, Object> paramsMap) {
        if (paramsMap.isEmpty()) {
            log.debug(sql);
            execute(sql);
            return;
        }

        if (!sql.contains("WHERE")) {
            sql += " WHERE 1=1 ";
        }
        StringBuilder newSql = new StringBuilder(sql);

        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            String mapKey = entry.getKey();
            Object mapValue = entry.getValue();
            newSql.append(" AND ").append(xxXToxx_x(mapKey)).append(" = '").append(mapValue).append("' ");
        }
        log.debug(newSql.toString());
        execute(newSql.toString());

    }

    public String joinSql(String sql, Map<String, Object> paramsMap) {
        if (paramsMap.isEmpty()) {
            return sql;
        }

        StringBuilder newSql = new StringBuilder("select * from ( ");

        newSql.append(sql).append(" ) ").append(" WHERE 1=1 ");

        for (Map.Entry<String, Object> entry : paramsMap.entrySet()) {
            String mapKey = entry.getKey();
            Object mapValue = entry.getValue();
            newSql.append(" and ").append(mapKey).append(" = '").append(mapValue).append("' ");
        }

        return newSql.toString();
    }

    public <T> PagerVO<T> queryForPage(String sql, Integer page, Integer pageSize, RowMapper<T> var3) {

        //获取记录条数
        String countSql = "select count(1) as count from (" + sql + ") temp";
        log.info("countSql {}", countSql);
        Long records = super.queryForObject(countSql, Long.class);

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(" ");
        stringBuilder.append("limit");
        stringBuilder.append(" ");
        if (page == 0) {
            stringBuilder.append("0");
        } else {
            stringBuilder.append((page - 1) * pageSize);
        }
        stringBuilder.append(",");
        stringBuilder.append(pageSize);
        sql += stringBuilder.toString();
        log.info("queryLimitSql {}", sql);
        List<T> data = super.query(sql, var3);

        return new PagerVO<T>(page, pageSize, records, data);

    }

    public String joinFilters(String sql, PageQueryRequest.Filters params, String sort) {
        StringBuilder sb = new StringBuilder(sql);
        if (params.getRules().size() > 0) {
            for (PageQueryRequest.Rules rule : params.getRules()) {
                sb.append(" ").append(params.getGroupOp());
                joinRule(sb,rule);
            }
        }
        if (!StringUtils.isBlank(sort)){
            sb.append(" ").append("ORDER BY ").append(xxXToxx_x(sort));
        }
        return sb.toString();
    }

    public StringBuilder joinRule(StringBuilder sb, PageQueryRequest.Rules rule) {
        sb.append(" ").append(xxXToxx_x(rule.getField())).append(" ");
        sb.append(SqlRules.valueOf(rule.getOp()).getValue()).append(" '");
        sb.append(rule.getData()).append("' ");
        return sb;
    }


    private String xxXToxx_x(String str) {
        Pattern compile = Pattern.compile("[A-Z]");
        Matcher matcher = compile.matcher(str);
        StringBuffer sb = new StringBuffer();
        while(matcher.find()) {
            matcher.appendReplacement(sb,  "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }
}
